package com.xinyue.gateway.server.handler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import com.xinyue.gateway.server.message.GateMessageHeader;
import com.xinyue.gateway.server.message.GateMessagePackage;
import com.xinyue.utils.NettyUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 * 解码从客户端接收的消息，详细见<a href = "https://www.cnblogs.com/wgslucky/p/9130993.html">网关的实现</a>
 * 
 * @Date 2018年6月14日 下午3:17:46
 */
@Service
@Scope(scopeName = "prototype")
public class GameMessageDecodeHandler extends ChannelInboundHandlerAdapter {
    private static Logger logger = LoggerFactory.getLogger(GameMessageDecodeHandler.class);
    // 当前已处理过的序列id
    private int nowSeqId;
    private String ip;

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ip = NettyUtil.getIp(ctx);
        ctx.fireChannelActive();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf = (ByteBuf) msg;
        try {
            short total = byteBuf.readShort();
            logger.debug("消息长度：{}", total);
            int seqId = byteBuf.readInt();
            if (nowSeqId != 0 && seqId < nowSeqId) {
                logger.error("消息序列号错误,收到序列号:{}，当前序列号:{}", seqId, nowSeqId);
                ctx.close();
                NettyUtil.releaseBuf(byteBuf);
                return;
            }
            if (seqId == nowSeqId) {
                NettyUtil.releaseBuf(byteBuf);
                logger.warn("消息已处理过，直接丢掉");
                return;
            }
            int messageId = byteBuf.readInt();
            long clientSendTime = byteBuf.readLong();
            byte version = byteBuf.readByte();
            GateMessagePackage messagePackage = new GateMessagePackage();
            if (byteBuf.readableBytes() > 0) {
                long crcValue = byteBuf.readLong();
                byte[] body = new byte[byteBuf.readableBytes()];
                byteBuf.readBytes(body);
                if (!this.checkCrc(crcValue, body)) {
                    logger.debug("消息不完整，非法");
                    ctx.close();
                    NettyUtil.releaseBuf(byteBuf);
                    return;
                }
                messagePackage.setBody(body);
            }
            GateMessageHeader messageHeader = new GateMessageHeader();
            messageHeader.setSendTime(clientSendTime);
            messageHeader.setMessageId(messageId);
            messageHeader.setSeqId(seqId);
            messageHeader.setIp(ip);
            messageHeader.setVersion(version);
            messagePackage.setHeader(messageHeader);
            nowSeqId = seqId;
            ctx.fireChannelRead(messagePackage);
        } catch (Exception e) {
            ctx.close();
            logger.error("服务器解析协议出错", e);
        } finally {
            NettyUtil.releaseBuf(byteBuf);
        }

    }

    private boolean checkCrc(long crc32, byte[] body) {
        if (body == null) {
            return true;
        }
        return true;
    }
}
